package com.baoyouqun.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.lang.tree.TreeNode;
import cn.hutool.core.lang.tree.TreeUtil;
import com.alibaba.cola.dto.Response;
import com.alibaba.cola.dto.SingleResponse;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.baoyouqun.base.SystemConstant;
import com.baoyouqun.base.utils.ConvertUtils;
import com.baoyouqun.domain.CreateCmd.PermissionCreateCmd;
import com.baoyouqun.domain.Query.PermissionQuery;
import com.baoyouqun.domain.UpdateCmd.PermissionUpdateCmd;
import com.baoyouqun.domain.VO.MenuTreeVO;
import com.baoyouqun.domain.VO.PermissionVO;
import com.baoyouqun.entity.Permission;
import com.baoyouqun.entity.Role;
import com.baoyouqun.entity.RolePermission;
import com.baoyouqun.mapper.PermissionMapper;
import com.baoyouqun.service.PermissionService;
import com.baoyouqun.service.RolePermissionService;
import com.baoyouqun.service.RoleService;
import com.baoyouqun.service.UserRoleService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.util.StringUtil;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
public class PermissionServiceImpl extends ServiceImpl<PermissionMapper, Permission> implements PermissionService {


    @Resource
    private PermissionMapper permissionMapper;
    @Resource
    private UserRoleService userRoleService;
    @Resource
    private RolePermissionService rolePermissionService;
    @Resource
    private RoleService roleService;

    @Override
    public SingleResponse<PermissionVO> create(PermissionCreateCmd cmd) {
        Permission entity =
                ConvertUtils.copyBean(cmd, Permission.class);
        Boolean result = save(entity);
        if (!result) {
            return SingleResponse.buildFailure("100101", "创建失败");
        }

        PermissionVO vo =
                ConvertUtils.copyBean(entity, PermissionVO.class);
        return SingleResponse.of(vo);
    }

    @Override
    public Response update(PermissionUpdateCmd cmd) {
        if (Objects.isNull(cmd)) {
            return Response.buildFailure("100301", "参数不能为空");
        }
        if (StringUtil.isBlank(cmd.getId())) {
            return Response.buildFailure("100302", "ID不能为空");
        }
        Permission oldEntity = getById(cmd.getId());
        if (Objects.isNull(oldEntity)) {
            return Response.buildFailure("100303", "未查询到此数据");
        }
        oldEntity = ConvertUtils.copyBean(cmd, Permission.class);
        Boolean result = updateById(oldEntity);
        if (result) {
            return Response.buildSuccess();
        } else {
            return Response.buildFailure("100304", "更新失败");
        }
    }

    @Override
    public PermissionVO selectById(String id) {
        Permission entity = getById(id);
        PermissionVO vo =
                ConvertUtils.copyBean(entity, PermissionVO.class);
        return vo;
    }

    @Override
    public IPage<PermissionVO> pageVo(PermissionQuery query) {
        IPage<Permission> page = new Page<>(query.getCurrent(), query.getSize());
        page = page(page, new LambdaQueryWrapper<>());
        Page<PermissionVO> voPage = new Page<>(page.getCurrent(), page.getSize(), page.getTotal());
        page.getRecords().forEach(entity -> {
            PermissionVO vo =
                    ConvertUtils.copyBean(entity, PermissionVO.class);
            voPage.getRecords().add(vo);
        });
        return voPage;
    }

    @Override
    public List<Tree<String>> getMenuTree() {
        // 1. 查询所有菜单（仅菜单类型，排除按钮）
        List<Permission> list = list(new LambdaQueryWrapper<Permission>().eq(Permission::getType, SystemConstant.PERMISSION_TYPE_MENU));
        // 2. 配置树形结构参数
        List<TreeNode<String>> nodeList = CollUtil.newArrayList();
        list.forEach(r -> {
//            TreeNode<String> node = new TreeNode<>(r.getId(), r.getPid(), r.getPermName(), Long.parseLong(r.getId()));
            TreeNode<String> node = new TreeNode<>(r.getId(), r.getPid(), r.getPermName(), r.getSort());
            node.setExtra(new HashMap<>(Map.of(
                    "icon", r.getIcon(),
                    "path", r.getPath(),
                    "permCode", r.getPermCode()
            )));
            nodeList.add(node);
        });
        return TreeUtil.build(nodeList, "0");
    }

    @Override
    public List<String> getPermissionList() {

        String roleId = userRoleService.getRoleIdByUserId(StpUtil.getLoginIdAsString());
        if (roleId == null) {
            return new ArrayList<>();
        }        // 2. 根据角色ID查权限ID列表
        LambdaQueryWrapper<RolePermission> rpWrapper = new LambdaQueryWrapper<>();
        rpWrapper.eq(RolePermission::getRoleId, roleId);
        List<String> permIds = rolePermissionService.list(rpWrapper).stream()
                .map(RolePermission::getPermId)
                .collect(Collectors.toList());
        if (CollUtil.isEmpty(permIds)) {
            return new ArrayList<>();
        }
        List<Permission> list = list(new LambdaQueryWrapper<Permission>().in(Permission::getId, permIds));
        return list.stream().map(Permission::getPermCode).collect(Collectors.toList());
    }
    
    @Override
    public SingleResponse<MenuTreeVO> getUserPermissionMenu(String userId) {
        // 1. 根据用户ID查角色ID（单角色）
        String roleId = userRoleService.getRoleIdByUserId(userId);
        if (roleId == null) {
            return null;
        }

        // 2. 根据角色ID查权限ID列表
        LambdaQueryWrapper<RolePermission> rpWrapper = new LambdaQueryWrapper<>();
        rpWrapper.eq(RolePermission::getRoleId, roleId);
        List<String> permIds = rolePermissionService.list(rpWrapper).stream()
                .map(RolePermission::getPermId)
                .collect(Collectors.toList());
        if (permIds.isEmpty()) {
            return null;
        }

        // 3. 根据权限ID列表查所有权限（按ID升序，保证层级顺序）
        LambdaQueryWrapper<Permission> permWrapper = new LambdaQueryWrapper<>();
        permWrapper.in(Permission::getId, permIds)
                .orderByAsc(Permission::getId); // 按ID升序=按层级排序
        List<Permission> permissionList = permissionMapper.selectList(permWrapper);

        // 4. 构建树形结构（一级菜单→子菜单→按钮）
        MenuTreeVO root = new MenuTreeVO();
        root.setPermName("权限根节点");
        root.setChildren(buildMenuTree(permissionList, "0")); // 父ID为空=一级菜单

        return SingleResponse.of(root);
    }


    @Override
    public SingleResponse<MenuTreeVO> getRolePermissionMenu(String roleId) {
        long totalStart = System.currentTimeMillis();
        log.info("开始查询角色权限菜单，roleId:{}", roleId);

        // 1. 查询角色信息
        long roleStart = System.currentTimeMillis();
        Role role = roleService.getById(roleId);
        log.info("查询角色信息耗时:{}ms，roleId:{}，角色是否存在:{}",
                System.currentTimeMillis() - roleStart, roleId, role != null);

        if (role == null) {
            return null;
        }

        // 2. 根据角色ID查权限ID列表
        long rpStart = System.currentTimeMillis();
        LambdaQueryWrapper<RolePermission> rpWrapper = new LambdaQueryWrapper<>();
        rpWrapper.eq(RolePermission::getRoleId, roleId);
        List<String> permIds = rolePermissionService.list(rpWrapper).stream()
                .map(RolePermission::getPermId)
                .collect(Collectors.toList());
        log.info("查询角色权限关联列表耗时:{}ms，roleId:{}，权限ID数量:{}",
                System.currentTimeMillis() - rpStart, roleId, permIds.size());

        if (permIds.isEmpty()) {
            return null;
        }

        // 3. 根据权限ID列表查所有权限
        long permStart = System.currentTimeMillis();
        LambdaQueryWrapper<Permission> permWrapper = new LambdaQueryWrapper<>();
        permWrapper.in(Permission::getId, permIds)
                .orderByAsc(Permission::getId);
        List<Permission> permissionList = permissionMapper.selectList(permWrapper);
        log.info("查询权限列表耗时:{}ms，权限数量:{}",
                System.currentTimeMillis() - permStart, permissionList.size());

        // 4. 构建树形结构
        long treeStart = System.currentTimeMillis();
        MenuTreeVO root = new MenuTreeVO();
        root.setPermName("权限根节点");
        root.setChildren(buildMenuTree(permissionList, "0"));
        log.info("构建权限树形结构耗时:{}ms", System.currentTimeMillis() - treeStart);

        log.info("查询角色权限菜单总耗时:{}ms，roleId:{}",
                System.currentTimeMillis() - totalStart, roleId);
        return SingleResponse.of(root);
    }

    /**
     * 递归构建菜单树形结构
     *
     * @param allPerm  所有权限列表
     * @param parentId 父权限ID
     * @return 子权限列表
     */
    private List<MenuTreeVO> buildMenuTree(List<Permission> allPerm, String parentId) {
        return allPerm.stream()
                // 筛选当前父ID的子权限
                .filter(perm -> parentId.equals(perm.getPid()))
                .map(perm -> {
                    MenuTreeVO menuVO = new MenuTreeVO();
                    menuVO.setId(perm.getId());
                    menuVO.setPermName(perm.getPermName());
                    menuVO.setType(perm.getType());
                    menuVO.setPath(perm.getPath());
                    // 递归构建子权限（按钮无children，子菜单有children）
                    menuVO.setChildren(buildMenuTree(allPerm, perm.getId()));
                    return menuVO;
                })
                .collect(Collectors.toList());
    }
}